package org.pz.filter;

import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.pz.http.HttpUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 认证过滤器
 * */
@Slf4j
public class RestfulUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    /**
     * 构造方法，设置登录接口和方法
     * 当请求这个 /login 时，会进入这个拦截器
     */
    public RestfulUsernamePasswordAuthenticationFilter() {
        /**
         * 这里设置和 UsernamePasswordAuthenticationFilter 一样，因为这个过滤器在前，这样会让 UsernamePasswordAuthenticationFilter 不生效
         * */
        setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
    }

    /**
     * 认证过程大致在这个方法中
     * 1. 从 requestBody 中获取认证信息
     * 2. 密码加解密
     * 3. 账户冻结，注销，登录错误次数过多锁定等情况判断
     * 4. 账户正常，判断账户密码是否正确
     * */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        log.info("认证流程第二步：UsernamePasswordAuthenticationFilter.attemptAuthentication 方法验证");

        /*
         * 1. 获取认证信息
         * */
        JSONObject requestBody = HttpUtils.getJsonObjectFromRequest(request);
        if(requestBody == null) {
            throw new RuntimeException("获取登录信息异常！");
        }
        String username = requestBody.getString(getUsernameParameter());
        String password = requestBody.getString(getPasswordParameter());

        /*
         * 2. 密码解密
         * */

        /*
         * 3. 查询账户，然后判断账户信息
         * */

        /*
         * 4. 使用 security 的校验逻辑
         * */
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,password);
        this.setDetails(request, authRequest);

        return this.getAuthenticationManager().authenticate(authRequest);
    }
}
